#! /bin/sh
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#

#
# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
#

. /lib/svc/share/smf_include.sh

AUDIT=/usr/sbin/audit
AUDITCONFIG=/usr/sbin/auditconfig
AUDITD=/usr/sbin/auditd
AWK=/usr/bin/gawk
EGREP=/usr/bin/egrep
MV=/usr/bin/mv
PKILL=/usr/bin/pkill
SLEEP=/usr/bin/sleep
SVCADM=/usr/sbin/svcadm
SVCCFG=/usr/sbin/svccfg
SVCS=/usr/bin/svcs

AUDIT_STARTUP=/etc/security/audit_startup
AUDITD_FMRI="system/auditd:default"

#
# main - the execution starts there.
main()
{
	#
	# Do the basic argument inspection and take the appropriate action.
	case "$SMF_METHOD" in
	start)
		do_common
		do_start
		;;
	refresh)
		do_common
		do_refresh
		;;
	*)
		if [ -z "$SMF_METHOD" ]; then
			echo "$0:  No SMF method defined."
		else
			echo "$0:  Unsupported SMF method: $SMF_METHOD."
		fi
		exit $SMF_EXIT_ERR_NOSMF
		;;
	esac
}
	
#
# do_common - executes all the code common to all supported service methods.
do_common()
{ 
	#
	# If the audit state is "disabled" auditconfig returns non-zero exit
	# status unless the c2audit module is loaded; if c2audit is loaded,
	# "disabled" becomes "noaudit" early in the boot cycle and "auditing"
	# only after auditd starts.
	AUDITCOND="`$AUDITCONFIG -getcond 2>/dev/null`"
	if [ $? -ne 0 ]; then
		# The decision whether to start
		# auditing is driven by bsmconv(8) / bsmunconv(8)
		echo "$0: Unable to get current kernel auditing condition."
		$SVCADM mark maintenance $AUDITD_FMRI
		exit $SMF_EXIT_MON_OFFLINE
	fi
	#
	# In a non-global zone, auditd is started/refreshed only if the
	# "perzone" audit policy has been set.
	if smf_is_nonglobalzone; then
		$AUDITCONFIG -t -getpolicy | \
		    $EGREP "perzone|all" 1>/dev/null 2>&1
		if [ $? -eq 1 ]; then
			echo "$0: auditd(8) is not configured to run in"
			echo "   a local zone, perzone policy not set" \
			    "(see auditconfig(8))."
			$SVCADM disable $AUDITD_FMRI
			$SLEEP 5 &
			exit $SMF_EXIT_OK
		fi
	fi
	#
	# Validate the audit service configuration
	val_err="`$AUDIT -v 2>&1`"
	if [ $? -ne 0 ]; then
		echo "$0: audit service misconfiguration detected (${val_err})"
		$SVCADM mark maintenance $AUDITD_FMRI
		exit $SMF_EXIT_MON_OFFLINE
	fi
}

#
# do_start - service start method helper.
do_start()
{
	#
	# The transition of the audit_startup(8) has to be performed.
	if [ -f "$AUDIT_STARTUP" ]; then
		
		if [ -x "$AUDIT_STARTUP" ]; then
			$AUDIT_STARTUP
		else
			echo "$0: Unable to execute $AUDIT_STARTUP"
			$SVCADM mark maintenance $AUDITD_FMRI
			exit $SMF_EXIT_MON_OFFLINE
		fi
		
		echo "$0: Transition of audit_startup(8) started."

		$MV $AUDIT_STARTUP $AUDIT_STARTUP._transitioned_
		if [ $? -ne 0 ]; then
			# Unable to perform the backup of $AUDIT_STARTUP
			echo "$0: The $AUDIT_STARTUP was not moved to"
			echo "   $AUDIT_STARTUP._transitioned_"
		fi

		#
		# Refreshing service to make the newly created properties
		# available for any other consequent svcprop(1).
		$SVCCFG -s $AUDITD_FMRI refresh
		if [ $? -ne 0 ]; then
			echo "$0: Refresh of $AUDITD_FMRI configuration failed."
			$SVCADM mark maintenance $AUDITD_FMRI
			exit $SMF_EXIT_ERR_CONFIG
		fi

		echo "$0: Transition of audit_startup(8) finished."
	fi

	#
	# Daemon forks, parent exits when child says it's ready.
	exec $AUDITD
}

#
# do_refresh - service refresh method helper.
do_refresh()
{
	#
	# The refresh capability is available only for those systems
	# with already transformed audit_startup(8) into $AUDITD_FMRI
	# service properties. See do_start() for more information.
	if [ ! -f "$AUDIT_STARTUP" ]; then
		#
		# Find the contract_id.
		contract_id=`$SVCS -l $AUDITD_FMRI | \
		    $AWK '/^contract_id/ {print $2}'`
		if [ -z "${contract_id}" ]; then
			echo "$0: Service $AUDITD_FMRI has no associated" \
			    "contract. Service cannot be refreshed."
			exit $SMF_EXIT_ERR_FATAL
		fi
		#
		# signal to auditd(8):
		$PKILL -HUP -c ${contract_id}
		if [ $? -ne 0 ]; then
			echo "$0: SIGHUP was not successfully delivered to" \
			    "the related contract (${contract_id}/err:$?)."
			$SVCADM mark maintenance $AUDITD_FMRI
			exit $SMF_EXIT_ERR_FATAL
		fi
		$SLEEP 5 &
	else 
		echo "$0: Service refresh method not supported on systems" \
		   "without converted audit_startup(8) into auditd service" \
		   "SMF configuration. Clear the service (svcadm(8))."
		$SVCADM mark maintenance $AUDITD_FMRI
		exit $SMF_EXIT_ERR_CONFIG
	fi
}

#
# Call main() to start the own script execution.
main
